es sql site server添加认证信息

Elasticsearch的权限可以通过search-guard或者xpack(shield)来实现,Elasticsearch-SQL也同步支持了权限认证,只需要把用户名和密码作为参数添加到url中就可以了,例如:http://domain/?base_uri=http://<es_addr>/&username=<usr>&password=<pwd>

具体实现也不复杂,只涉及到前端controllers.js的改动

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// settings
var settings = location.search.substring(1).split("&").reduce(function (r, p) {
r[decodeURIComponent(p.split("=")[0])] = decodeURIComponent(p.split("=")[1]);
return r;
}, {});

var elasticsearchSqlApp = angular.module('elasticsearchSqlApp', ["ngAnimate", "ngSanitize"]);

// auth
if (settings['username']) localStorage.setItem("auth", "Basic " + window.btoa(settings['username'] + ":" + settings['password']));
if (localStorage.getItem("auth")) {
elasticsearchSqlApp.config(function ($httpProvider) {
$httpProvider.interceptors.push(function () {
return {
request: function (config) {
config.headers['Authorization'] = localStorage.getItem("auth");
return config;
}
};
});
});
}

通过location.search读取url中的用户名和密码,然后用window.btoa转成base64字符串组装认证header

1
2
3
headers: {
"Authorization": "Basic " + window.btoa(username + ":" + password)
}

认证信息通过修改$httpProvider对所有的$http生效,这样所有的es请求(/,/_nodes,/_sql,/_sql,/_explain等等)都会带上认证信息,然后在elasticsearch.yml中配置允许http请求就可以了

1
2
3
http.cors.enabled: true

http.cors.allow-origin: "*"

但并不能正常使用,界面显示异常

Error occured! response is not avalible.

DEBUG信息显示

Request header field Authorization is not allowed by Access-Control-Allow-Headers in preflight response.

后端服务不允许在header中使用Authorization。解决方法是在elasticsearch.yml中添加配置

1
http.cors.allow-headers: "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With, Content-Length"

http.cors.allow-headers的默认值是X-Requested-With, Content-Type, Content-Length,修改之后就能通过认证并进行ES SQL查询了

另外还发现一个小问题,当访问了一个需要认证的ES集群之后,再访问另一个不需要认证的集群,就访问失败,原因是第一次访问之后前端缓存localStorage中就带有认证信息,第二次访问由于没有带用户名和密码参数,所以localStorage不会更新,导致第二次访问也带上了缓存的认证信息,导致访问失败。解决办法也比较简单,如果参数中没有用户名和密码,就把localStorage中的auth清空就行

1
2
3
4
5
if (settings['username']) {
localStorage.setItem("auth", "Basic " + window.btoa(settings['username'] + ":" + settings['password']));
} else {
localStorage.removeItem("auth");
}